package main

import (
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"os"
	"strings"
)

//type Studuent struct {
//	Name string
//	Age  int
//}
//xml是小写的，使用tag指定
//type Studuent struct {
//	XMLName xml.Name        "xml:'student'"
//	Name    string        "xml:'name'"
//	Age     int        "xml:'age'"
//	Phone   []string        "xml:'Phones>phone',"
//}
//指定解码/编码对应的json名
type Studuent struct {
	Name string        "json:'userName'"
	Age  int
}
//默认序列化
func serialize() {
	s := &Studuent{Name:"ldw", Age:30}
	f, err := os.Create("data.dat")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer f.Close()
	encode := gob.NewEncoder(f)
	encode.Encode(s)

	f.Seek(0, os.SEEK_SET)
	decoder := gob.NewDecoder(f)
	var s1 Studuent
	decoder.Decode(&s1)
	fmt.Println(s1)
}
//xml序列化
func serializeXML() {
	f, err := os.Create("data.dat")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer f.Close()
	s := &Studuent{Name:"ldw", Age:30}
	encoder := xml.NewEncoder(f)
	encoder.Encode(s)
	f.Seek(0, os.SEEK_SET)
	decoder := xml.NewDecoder(f)
	var s1 Studuent
	decoder.Decode(&s1)
	fmt.Println(s1)
}
//xml.Marshal直接序列化对象到字符
func marshal() {
	s := &Studuent{Name:"ldw", Age:30}
	result, err := xml.Marshal(s)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(string(result))
}
//反序列化
func unmarshal() {
	str := "<?xml version='1.0' encoding='utf-8'?>" +
		"<Student>" +
		"<Name>ldw</Name>" +
		"<Age>30</Age>" +
		"</Student>"
	var s Studuent
	xml.Unmarshal([]byte(str), &s)
	fmt.Println(s)
}
func unmarshal2() {
	str := "<?xml version='1.0' encoding='utf-8'?>" +
		"<student>" +
		"<name>ldw</name>" +
		"<age>30</age>" +
		"<phones>" +
		"<phone>1234</phone>" +
		"<phone>12345</phone>" +
		"</phones>" +
		"</student>"
	var s Studuent
	xml.Unmarshal([]byte(str), &s)
	fmt.Println(s)
}
//token解析是最快的，对于大文件，要求性能的，这种方式最好
func xmlReader() {
	str := "<?xml version='1.0' encoding='utf-8'?>" +
		"<Student>" +
		"<Name>ldw</Name>" +
		"<Age>30</Age>" +
		"</Student>"
	decoder := xml.NewDecoder(strings.NewReader(str))
	var strName string
	for {
		token, err := decoder.Token()
		if err != nil {
			break
		}
		switch t := token.(type) {
		case xml.StartElement:
			stelm := xml.StartElement(t)
			fmt.Println("Start ", stelm.Name.Local)
			strName = stelm.Name.Local
		case xml.EndElement:
			endelem := xml.EndElement(t)
			fmt.Println("End", endelem.Name.Local)
		case xml.CharData:
			data := xml.CharData(t)
			str := string(data)
			switch strName {
			case "Name":
				fmt.Println("姓名：", str)
			case "Age":
				fmt.Println("年龄：", str)
			default:
				fmt.Println("other:", str)
			}
		}
	}
}
//
func serializeJSON() {
	f, err := os.Create("data.dat")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer f.Close()
	s := &Studuent{Name:"ldw", Age:30}
	encoder := json.NewEncoder(f)
	encoder.Encode(s)
	f.Seek(0, os.SEEK_SET)
	decoder := json.NewDecoder(f)
	var s1 Studuent
	decoder.Decode(&s1)
	fmt.Println(s1)
}

func unmarshalJSON() {
	s := &Studuent{Name:"ldw", Age:30}
	result, err := json.Marshal(s)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(string(result))
	var s1 Studuent
	json.Unmarshal(result, &s1)
	fmt.Println(s1)
}

func unmarshalJSON2() {
	//TODO
	str := "{'userName':'ldw','Age':30}"
	var m map[string]interface{}
	json.Unmarshal([]byte(str), &m)
	for k, v := range m {
		switch v.(type) {
		case float64:
			fmt.Println(k, "是 int 类型，值为：", v)
		case string:
			fmt.Println(k, "是 string 类型，值为：", v)
		default:
			fmt.Println(k, "无法用别的类型", v)

		}
	}
}

func main() {
	//serialize()
	//serializeXML()
	//marshal()
	//unmarshal()
	//unmarshal2()
	//xmlReader()
	//serializeJSON()
	//unmarshalJSON()
	unmarshalJSON2()
}
